package ru.amse.tsyganov.jumleditor.view;

import static java.lang.Math.PI;

import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import ru.amse.tsyganov.jumleditor.model.ActivityGraph;
import ru.amse.tsyganov.jumleditor.model.State;
import ru.amse.tsyganov.jumleditor.properties.EnumProperty;
import ru.amse.tsyganov.jumleditor.properties.StringProperty;

public abstract class DecisionView<T extends State> extends StateView<T> {

	private static final String HORIZONTAL_POSITION = "horizontalPosition";
	
	private final static int DECISION_DEFAULT_WIDTH = 40;
	
	private final static int DECISION_DEFAULT_HEIGHT = 20;
	
	private boolean horizontalPosition = true;
	
	public DecisionView(T model, 
			ActivityGraphView<? extends ActivityGraph> activityGraphView) {
		
		super(model, activityGraphView);
		
		setWidth(DECISION_DEFAULT_WIDTH);
		setHeight(DECISION_DEFAULT_HEIGHT);
		
		initProperties();
	}
	
	@Override
	public void readFromXml(Node element) {
		super.readFromXml(element);
		horizontalPosition = Boolean.parseBoolean(
				element.getAttributes().
				getNamedItem(HORIZONTAL_POSITION).getNodeValue());
	}

	@Override
	public void writeToXml(Element element) {
		super.writeToXml(element);
		element.setAttribute(HORIZONTAL_POSITION, 
				Boolean.toString(horizontalPosition));
	}
	
	public abstract Color getFillColor();

	@Override
	public void prepaintEvent(GC gc) {
	}

	@Override
	public void paintFigure(GC gc) {
		assert gc != null;
		
		int L = horizontalPosition ? getWidth() / 4 : getHeight() / 4;
		
		int[] polygon = horizontalPosition ?
				new int[] {
				getX() + getWidth() / 2, getY(),
				getX() + getWidth() - L, getY() + getHeight() / 2,
				getX() + getWidth() / 2, getY() + getHeight(),
				getX() + L, getY() + getHeight() / 2
				} :
					
				new int[] {
				getX() + getWidth() / 2, getY() + L,
				getX() + getWidth(), getY() + getHeight() / 2,
				getX() + getWidth() / 2, getY() + getHeight() - L,
				getX(), getY() + getHeight() / 2
				};
				
				
		gc.setBackground(getFillColor());
		gc.fillPolygon(polygon);
		
		gc.setForeground(getValidity().getColor());
		gc.setLineWidth(getValidity().getLineWidth());
		gc.drawPolygon(polygon);
		
		if (horizontalPosition) {
			gc.drawLine(getX() + getWidth() - L, getY() + getHeight() / 2, 
				getX() + getWidth(), getY() + getHeight() / 2);
			gc.drawLine(getX() + L, getY() + getHeight() / 2,
					getX(), getY() + getHeight() / 2);
		} else {
			gc.drawLine(getX() + getWidth() / 2, getY() + getHeight() - L,
				getX() + getWidth() / 2, getY() + getHeight());
			gc.drawLine(getX() + getWidth() / 2, getY() + L, 
					getX() + getWidth() / 2, getY());
		}
		gc.setLineWidth(0);
	}
	
	@Override
	public StringProperty getMainProperty() {
		return null;
	}
	
	@Override
	public Point getConnectionPoint(Point sourcePoint, boolean in) {
		Point top = new Point(getX() + getWidth() / 2, getY());
		Point right = new Point(getX() + getWidth(), getY() + getHeight() / 2);
		Point bottom = new Point(getX() + getWidth() / 2, getY() + getHeight());
		Point left = new Point(getX(), getY() + getHeight() / 2);
		
		double a = Math.atan2(getCenterPoint().y - sourcePoint.y, 
					sourcePoint.x - getCenterPoint().x);
		
		if (horizontalPosition) {
			if (!in) {
				if (a > 0 && a <= PI) {
					return top;
				} else {
					return bottom;
				}
			} else {
				if (a > -PI / 2 && a <= PI / 2) {
					return right;
				} else {
					return left;
				}
			}
		} else {
			if (!in) {
				if (a > -PI / 2 && a <= PI / 2) {
					return right;
				} else {
					return left;
				}
			} else {
				if (a > 0 && a <= PI) {
					return top;
				} else {
					return bottom;
				}
			}
		}
	}
	
	private void initProperties() {
		String[] elements = {"Vertical", "Horizontal"};
		
		super.getProperties().addProperty(
				new EnumProperty("Position", elements) {

			@Override
			public Integer getPropertyValue() {
				return (horizontalPosition) ? 1 : 0;
			}

			@Override
			public void setPropertyValue(Integer newValue) {
				if (horizontalPosition != (newValue == 1)) {
					int i = getWidth();
					setWidth(getHeight());
					setHeight(i);
					horizontalPosition = (newValue == 1);
				}
			}

		});
	}

}
